from collections import defaultdict
from multiprocessing import Process

import cv2
import datetime
import json
import multiprocessing
import os
import random
import time
from copy import copy
from loguru import logger

from Ling.common.utils.OcrUtils import get_lines_from_file, \
    get_random_items, filter_line_in, get_dict_from_file, get_file_mapping, sort_mapping_by_value, get_txt_from_file, \
    labels_split, parse_char_num_mapping_of_file
from text_renderer.config import get_cfg
from text_renderer.render import Render

gl_char_img_num = defaultdict(int)
out_path = 'D:/ocr/ocr_resources/reader/train_data/train_data_v3'
font_root = 'D:/ocr/ocr_resources/reader/fonts/'
save_path = 'D:/ocr/ocr_resources/reader/train_data/char_enum_by_font/'
save_path_no_dot = 'D:/ocr/ocr_resources/reader/train_data/char_enum_by_font_no_dot/'
dict_10 = 'D:/ocr/ocr_resources/reader/dict_10/'  # 不为标点单独处理
dict_10_no_dot = 'D:/ocr/ocr_resources/reader/dict_10_no_dot/'
pre_char_texts_mapping_path_10 = 'D:/ocr/ocr_resources/reader/all_words/pre_json_char_texts_mapping.txt'
pre_char_texts_mapping_path_10_no_dot = 'D:/ocr/ocr_resources/reader/all_words/pre_json_char_texts_mapping_10_no_dot.txt'

dot_dict_file = 'D:/workspace/python/train_data/train_data_configs/words/font/in_chars_dot.txt'

root = 'D:/workspace/python/train_data/'
dictRoot = root + 'train_data_configs/words/'
reader_root = 'D:/ocr/ocr_resources/reader/'

lock = multiprocessing.Lock()

is_debug = False

STOP_TOKEN = "kill"


class EnumRender:
    def __init__(
            self,
            num_image=None,
            save_dir=None,
            texts=None,
            font_path=None
    ):
        generator_cfgs = get_cfg('config/enum.py')
        generator_cfg = generator_cfgs[0]
        render_cfg = generator_cfg.render_cfg
        corpus = render_cfg.corpus
        corpu = corpus[0]
        corpus_cfg = corpu.cfg
        corpus_cfg.text_paths = []
        self.generator_cfgs = generator_cfgs

        if num_image:
            self.set_num_image(num_image)
        if save_dir:
            self.set_save_dir(save_dir)
        if texts:
            self.set_texts(texts)
        if font_path:
            self.set_font_path(font_path)

    def set_texts(self, texts):
        corpu = self.generator_cfgs[0].render_cfg.corpus[0]
        corpu.texts = texts

    def set_font_path(self, font_path):
        if font_path is not None:
            corpu = self.generator_cfgs[0].render_cfg.corpus[0]
            corpu.cfg.font_list_file = font_path
            corpu.font_manager.load_font(font_path, None)

    def set_num_image(self, num_image):
        generator_cfg = self.generator_cfgs[0]
        generator_cfg.num_image = num_image

    def set_save_dir(self, save_dir):
        generator_cfg = self.generator_cfgs[0]
        generator_cfg.save_dir = save_dir

    def process_img(self):
        datas = []
        if is_debug:
            data = (None, self.generator_cfgs[0].render_cfg.corpus[0].texts[0])
            datas.append(data)
        else:
            if self.generator_cfgs[0].render_cfg.corpus[0].texts is None: raise 'texts不能为空'
            if self.generator_cfgs[0].num_image is None: raise 'num_image不能为空'
            if self.generator_cfgs[0].render_cfg.corpus[0].cfg.font_list_file is None: raise 'font_path不能为空'
            for generator_cfg in self.generator_cfgs:
                render = Render(generator_cfg.render_cfg)
                for _ in range(generator_cfg.num_image):
                    data = render()
                    if data is not None:
                        datas.append(data)
        return datas


class RandRender:
    def __init__(
            self,
            num_image=None,
            save_dir=None,
            all_chars=None,
            font_path=None
    ):
        generator_cfgs = get_cfg('config/rand.py')
        generator_cfg = generator_cfgs[0]
        render_cfg = generator_cfg.render_cfg
        corpus = render_cfg.corpus
        corpu = corpus[0]
        corpus_cfg = corpu.cfg
        corpus_cfg.text_paths = []
        self.generator_cfgs = generator_cfgs

        if num_image:
            self.set_num_image(num_image)
        if save_dir:
            self.set_save_dir(save_dir)
        if all_chars:
            corpu.cfg.chars_file = None
            corpu.chars = all_chars
        if font_path:
            self.set_font_path(font_path)

    def set_all_chars(self, all_chars):
        corpu = self.generator_cfgs[0].render_cfg.corpus[0]
        corpu.chars = all_chars

    def get_all_chars(self):
        corpu = self.generator_cfgs[0].render_cfg.corpus[0]
        return corpu.chars

    def set_font_path(self, font_path):
        if font_path is not None:
            corpu = self.generator_cfgs[0].render_cfg.corpus[0]
            corpu.cfg.font_list_file = font_path
            corpu.font_manager.load_font(font_path, None)

    def set_num_image(self, num_image):
        generator_cfg = self.generator_cfgs[0]
        generator_cfg.num_image = num_image

    def set_save_dir(self, save_dir):
        generator_cfg = self.generator_cfgs[0]
        generator_cfg.save_dir = save_dir

    def process_img(self):
        datas = []
        if self.generator_cfgs[0].render_cfg.corpus[0].chars is None: raise 'chars不能为空'
        if self.generator_cfgs[0].render_cfg.corpus[0].cfg.font_list_file is None: raise 'font_path不能为空'
        for generator_cfg in self.generator_cfgs:
            render = Render(generator_cfg.render_cfg)
            num_img = 1 if generator_cfg.num_image is None else generator_cfg.num_image
            for _ in range(num_img):
                data = render()
                if data is not None:
                    datas.append(data)
        return datas


class DBWriterProcess(Process):
    def __init__(
            self,
            data_queue,
            save_path,
            corp_img=False
    ):
        super().__init__()
        self.data_queue = data_queue
        self.save_path = save_path
        self.corp_img = corp_img

    def run(self):
        save_path = self.save_path
        log_period = 100
        logger.info(f"begin process DBWriterProcess")
        try:
            if not os.path.exists(save_path):
                os.makedirs(save_path)
            _img_dir = save_path + 'images'
            if not os.path.exists(_img_dir):
                os.makedirs(_img_dir)

            label_path = save_path + 'labels.txt'
            exist_count = 0
            if os.path.exists(label_path):
                with open(label_path, 'r', encoding='utf-8') as l:
                    lines = l.readlines()
                    exist_count = len(lines)
            count = 0
            logger.info(f"Exist image count in {save_path}: {exist_count}")
            start = time.time()
            with open(save_path + 'log.txt', 'a', encoding='utf-8') as log:
                with open(label_path, "a", encoding="utf-8") as f:
                    while True:
                        data_queue = self.data_queue
                        data = data_queue.get()
                        if data == STOP_TOKEN:
                            logger.info("DBWriterProcess receive stop token")
                            break

                        name = "{:09d}".format(exist_count + count)
                        # save img
                        image = data['image']
                        if image is not None:
                            img_path = _img_dir + '/' + name + ".jpg"

                            if self.corp_img:
                                # 获取图片的宽度和高度
                                height, width = image.shape[:2]

                                # 设置裁剪的左上角和右下角坐标
                                # 注意：OpenCV中的坐标是以左上角为原点的
                                x1, y1 = int(0), int(height * random.randint(10, 20) * 0.01)  # 随机裁剪范围
                                x2, y2 = int(width), int(height * random.randint(80, 90) * 0.01)  # 随机裁剪范围

                                # 使用切片操作进行裁剪
                                image = image[y1:y2, x1:x2]  # 3,28 25,231==>22,22 0,326

                            cv2.imwrite(img_path, image, [int(cv2.IMWRITE_JPEG_QUALITY), 95])
                            # save label
                            height, width = image.shape[:2]
                        else:
                            height, width = (0, 0)
                        label = data['label']
                        # 换行bug
                        label = label.replace('\r', '').replace('\n', '').replace('\t', '')
                        line = name + '\t' + label + '\t' + str(height) + '\t' + str(width)
                        f.write(line + '\n')

                        try:
                            char = data['char']
                            text = data['text']
                            font = data['font']
                            info = 'total:{} char:{} in text:{} with font:{} save:{}'.format(count, char, text, font,
                                                                                             name)
                            log.write(info + '\n')
                            # 打印下吧,不然等待起来很纠结
                            print(info)
                        except Exception as e:
                            font = data['font']
                            info = 'total:{} save:{} with font:{}'.format(count, name, font)
                            log.write(info + '\n')
                            # 打印下吧,不然等待起来很纠结
                            print(info)

                        count += 1
                        if count % log_period == 0:
                            logger.info(
                                # f"{(count / num_image) * 100:.2f}%({count}/{num_image}) {log_period / (time.time() - start + 1e-8):.1f} img/s"
                                f"{count}  {log_period / (time.time() - start + 1e-8):.1f} img/s"
                            )
                            start = time.time()

        except Exception as e:
            logger.exception("DBWriterProcess error")
            raise e
        finally:
            logger.info(f"end process DBWriterProcess generate: {count}.")


def process_char_lines(dict_in, char, line_num, reader_dict_root):
    # print('begin load char:' + char)
    lines = get_lines_from_file(reader_dict_root + char + '.txt')
    if len(lines) > 0:
        get_line_num = int(line_num * 1.5)
        # 取得字符串
        lines = get_random_items(lines, get_line_num)
        if dict_in is None:
            return lines
        else:
            return filter_char_lines(lines, dict_in, char)
    else:
        return []


def filter_char_lines(lines, dict_in, char):
    # 保证字符串的文字都能生成
    lines = filter_line_in(lines, dict_in)
    # 取得的是与char有关的字符串
    lines_filter = []
    for line in lines:
        if line.find(char) >= 0:
            lines_filter.append(line)
    return lines_filter


def load_font_render_mapping(font_root):
    fonts = [f for f in os.listdir(font_root) if f.lower().endswith('ttc') or f.lower().endswith('ttf')]
    font_render_mapping = defaultdict()

    font_num = 1 if is_debug else 9999
    for pos, font in enumerate(fonts):
        if pos < font_num:
            print('begin load font:{} {} of {}'.format(font, pos, len(fonts)))
            enum_render = EnumRender()
            enum_render.set_font_path(font_root + font)
            font_render_mapping[font] = enum_render
        else:
            break
    return font_render_mapping


def load_font_render_mapping_rand(font_root):
    fonts = [f for f in os.listdir(font_root) if f.lower().endswith('ttc') or f.lower().endswith('ttf')]
    font_render_mapping = defaultdict()

    font_num = 1 if is_debug else 9999
    for pos, font in enumerate(fonts):
        if pos < font_num:
            print('begin load font:{} {} of {}'.format(font, pos, len(fonts)))
            render = RandRender()
            render.set_font_path(font_root + font)
            font_render_mapping[font] = render
        else:
            break
    return font_render_mapping


def load_font_char_mapping(font_root):
    fonts = [f for f in os.listdir(font_root) if f.lower().endswith('ttc') or f.lower().endswith('ttf')]
    # font支持的字符映射
    font_char_mapping = defaultdict()
    font_list = []
    # 预加载数据
    for pos, font in enumerate(fonts):
        print('begin load font:{} {} of {}'.format(font, pos, len(fonts)))
        font_dict_in = get_dict_from_file(font_root + font + '.txt')
        font_char_mapping[font] = font_dict_in
        font_list.append(font_root + font)
    return font_char_mapping, font_list


def get_char_texts_mapping(char_num_path, line_num, char_root):
    char_img_num = defaultdict(int)
    char_texts_mapping = defaultdict(list)
    mapping = get_file_mapping(char_num_path, '\t')
    mapping = sort_mapping_by_value(mapping)
    for pos, char in enumerate(mapping.keys()):
        # char_num = char_img_num[char]
        # 这里有问题,因为如果这个字符出现在了别的语句中,但生成的时候是从所有里面挑选的,
        # 但不一定真能挑选到包含这个字符的语句,但又没有生成这个字符对应的texts,所以会导致这个出现频率高的字符反而不会被生成出来
        # if char_num <= max_num:
        #     texts = process_char_lines(None, char, 200, char_root)
        texts = process_char_lines(None, char, line_num, char_root)
        for text in texts:
            for c in text:
                char_img_num[c] = char_img_num[c] + 1
        char_texts_mapping[char] = texts
    char_img_num_sort = sort_mapping_by_value(char_img_num)
    return char_texts_mapping, char_img_num_sort


def pre_json_char_texts_mapping(char_num_path, out_path, char_root):
    char_texts_mapping, char_img_num_sort = get_char_texts_mapping(char_num_path, 500, char_root)
    with open(out_path, 'w', encoding='utf-8') as f:
        json.dump(char_texts_mapping, f, indent=4, ensure_ascii=False, sort_keys=True)
    with open(out_path.replace('.txt', '') + '_char_num.txt', 'w', encoding='utf-8') as f:
        for key in char_img_num_sort:
            f.write(key + '\t' + str(char_img_num_sort[key]) + '\n')


def load_char_texts_mapping(pre_char_texts_mapping_path):
    with open(pre_char_texts_mapping_path, 'r', encoding='utf-8') as f:
        char_texts_mapping = json.load(f)
    path = pre_char_texts_mapping_path.replace('.txt', '') + '_char_num.txt'
    char_img_num_sort = get_file_mapping(path, '\t')
    return char_texts_mapping, char_img_num_sort


def get_rand_support_font(text, font_char_mapping, font_render_mapping, char_dict_dot):
    fonts = list(font_render_mapping.keys())
    font = random.choice(fonts)
    char_dict_in = font_char_mapping[font]
    if is_text_in_dict(text, char_dict_in, char_dict_dot):
        return font_render_mapping[font], font
    return get_rand_support_font(text, font_char_mapping, font_render_mapping, char_dict_dot)


def is_text_in_dict(text, char_dict_in, char_dict_dot):
    for char in text:
        if char not in char_dict_dot and char not in char_dict_in:
            return False
    return True


# def t_error(save_path):
#     text = '㐶'
#     files = [f for f in os.listdir(font_root) if f.lower().endswith('ttc') or f.lower().endswith('ttf')]
#     # font = '方正悠黑系列_511M.ttf'
#     # font = 'Deng.ttf'
#     for f in files:
#         try:
#             enum_render = EnumRender(save_dir=save_path)
#             enum_render.set_font_path(font_root + f)
#             enum_render.set_num_image(1)
#             enum_render.set_texts([text])
#             enum_render.process_img()
#         except:
#             print(f)


def run_by_round(font_char_mapping, font_render_mapping, char_texts_mapping, char_img_num_sort, img_pre_name,
                 data_queue, char_dict_dot, char_appear_num):
    # 每轮每个字符至少出现一次,当出现次数大于10,不再为其专门读取texts生成图片
    # 10可能有点低,那些常用字符的关联字符会出现过拟合
    # 此方法执行200次,那么,每个字符最少出现200次
    # 有此方法后就可以多线程了

    # 104.53125 Seconds 这里耗时太长了,还是需要预加载的方式来实现,添加预加载的行数,来提高随机的质量
    # get_char_texts_mapping_start = time.process_time()
    # char_texts_mapping, char_img_num_sort = get_char_texts_mapping(
    #     reader_root + 'all_words/char_num_sort_10_no_dot.txt', 2,char_root)
    # get_char_texts_mapping_end = time.process_time()
    # print('get_char_texts_mapping time: %s Seconds' % (get_char_texts_mapping_end - get_char_texts_mapping_start))
    print('begin run_by_round')
    round_char_img_num = defaultdict(int)
    for pos, char in enumerate(char_img_num_sort):
        char_num = round_char_img_num[char]
        _total = data_queue.qsize()
        if (is_debug and '醍' == char):
            print('debug')
        # if char_num <= 20:
        if char_num <= char_appear_num:
            if char in char_texts_mapping:
                text = random.choice(char_texts_mapping[char])
                try:
                    enum_render, font = get_rand_support_font(text, font_char_mapping, font_render_mapping,
                                                              char_dict_dot)
                except Exception as e:
                    print('text:' + text + str(e))
                    raise e
                enum_render.set_num_image(1)
                enum_render.set_texts([text])
                datas = enum_render.process_img()
                for data in datas:
                    data_queue.put({"image": data[0], "label": data[1], "char": char, "text": text, "font": font})
                for c in text:
                    round_char_img_num[c] = round_char_img_num[c] + 1
            else:
                print('ignore key:' + char)
    print('end run_by_round')


def run_by_round_rand(font, render, data_queue, font_char_num):
    # 字符数*font_char_num/每张图字数 保证每个字体出现一次 总计122*1778=21万左右,如果出现10次,需要210万
    all_chars = render.get_all_chars()
    img_num = 20 if is_debug else int(len(all_chars) * font_char_num / 10) + 1
    # img_num = int(len(all_chars) * font_char_num / 10) + 1
    for i in range(0, img_num):
        datas = render.process_img()
        for data in datas:
            data_queue.put({"image": data[0], "label": data[1], "font": font})


def write_datas(datas, save_dir):
    if not os.path.exists(save_dir):
        os.makedirs(save_dir)
    _img_dir = save_dir + 'images'
    if not os.path.exists(_img_dir):
        os.makedirs(_img_dir)
    label_path = os.path.join(save_dir, 'labels.txt')
    with open(label_path, "a", encoding="utf-8") as f:
        for pos, data in enumerate(datas):
            name = "{:09d}".format(pos)
            label = data['label']
            # 换行bug
            label = label.replace('\r', '').replace('\n', '').replace('\t', '')
            image = data['image']
            img_path = _img_dir + '/' + name + ".jpg"
            # img_path = img_path.encode(encoding='gb2312')
            cv2.imwrite(img_path, image, [int(cv2.IMWRITE_JPEG_QUALITY), 95])
            height, width = image.shape[:2]
            line = name + '\t' + label + '\t' + str(height) + '\t' + str(width)
            f.write(line + '\n')


def process_setup(*args):
    import numpy as np
    # Make sure different process has different random seed
    np.random.seed()
    # logger.info(f"Finish setup image generate process: {os.getpid()}")


def round_by_pool(font_root, save_path, pre_char_texts_mapping_path, batch_num, char_appear_num):
    load_char_texts_mapping_start = time.process_time()
    char_texts_mapping, char_img_num_sort = load_char_texts_mapping(pre_char_texts_mapping_path)
    # 去掉标点符号
    char_dot = get_dict_from_file(dot_dict_file) + dict_error
    char_img_num_sort_new = defaultdict(int)
    for key in char_img_num_sort:
        if key not in char_dot:
            if key == '醍':
                print(1)
            char_img_num_sort_new[key] = char_img_num_sort[key]
        else:
            print('ignore char:' + key)

    load_char_texts_mapping_end = time.process_time()
    print('load_char_texts_mapping time: %s Seconds' % (load_char_texts_mapping_end - load_char_texts_mapping_start))

    font_char_mapping_start = time.process_time()
    font_char_mapping = load_font_char_mapping(font_root)
    font_char_mapping_end = time.process_time()
    # 1.171875 Seconds
    print('font_char_mapping_start time: %s Seconds' % (font_char_mapping_end - font_char_mapping_start))

    load_font_render_mapping_start = time.process_time()
    font_render_mapping = load_font_render_mapping(font_root)
    load_font_render_mapping_end = time.process_time()
    # 80s
    print('load_font_render_mapping time: %s Seconds' % (load_font_render_mapping_end - load_font_render_mapping_start))

    char_dict_dot = get_dict_from_file(dot_dict_file)

    multiprocessing.set_start_method("spawn", force=True)
    manager = multiprocessing.Manager()
    data_queue = manager.Queue()

    db_writer_process = DBWriterProcess(
        data_queue, save_path
    )
    db_writer_process.start()

    _processes_num = 1 if is_debug else 8
    # pool = multiprocessing.Pool(processes=_processes_num)
    with multiprocessing.Pool(
            # processes=_processes_num,
            # initializer=process_setup,
            # initargs=(),
    ) as pool:
        # 是8的倍数,不单跑,另外不宜过多,否则跑着跑着就单线程了 执行轮数
        _max_rang = 1 if is_debug else batch_num
        for i in range(0, _max_rang):
            font_render_mapping_ = defaultdict()
            # copy font_render_mapping
            for font in font_render_mapping:
                font_render_mapping_[font] = copy(font_render_mapping[font])
            # 开始多进程处理
            pool.apply_async(run_by_round,
                             (
                                 font_char_mapping, font_render_mapping_, char_texts_mapping, char_img_num_sort_new,
                                 str(i),
                                 data_queue, char_dict_dot, char_appear_num))
            # run_by_round(font_char_mapping, font_render_mapping_, char_texts_mapping, char_img_num_sort, str(i))
        pool.close()
        pool.join()

    data_queue.put(STOP_TOKEN)
    db_writer_process.join()


# 此方式会检查字体是否支持字符,导致很慢
def round_by_pool_rand_barkup(font_root, save_path, font_char_num):
    render = RandRender()
    font_char_mapping, font_list = load_font_char_mapping(font_root)
    # font_list = ['D:/ocr/ocr_resources/reader/fonts/Dengl.ttf']
    render.set_font_path(font_list)

    chars_text1 = get_txt_from_file(dictRoot + 'font/in_chars.txt').replace('\n', '')
    all_chars = "!\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}‖①②③④⑤⑥⑦⑧⑨⑩· … 。 《》" + chars_text1

    render.set_all_chars(all_chars)

    # 字符数*font_char_num/每张图字数
    num_image = int(len(all_chars) * font_char_num / 10) + 1

    multiprocessing.set_start_method("spawn", force=True)
    manager = multiprocessing.Manager()
    data_queue = manager.Queue()

    db_writer_process = DBWriterProcess(
        data_queue, save_path
    )
    db_writer_process.start()

    _processes_num = 2 if is_debug else 8
    # pool = multiprocessing.Pool(processes=_processes_num)
    with multiprocessing.Pool(
            # processes=_processes_num,
            # initializer=process_setup,
            # initargs=(),
    ) as pool:
        for _ in range(num_image):
            pool.apply_async(generate_img, args=(render, data_queue))
        pool.close()
        pool.join()

    data_queue.put(STOP_TOKEN)
    db_writer_process.join()


def generate_img(render, data_queue):
    datas = render.process_img()
    for data in datas:
        data_queue.put({"image": data[0], "label": data[1]})


def round_by_pool_rand(font_root, save_path, font_char_num, corp_img):
    # 单个font 10分钟
    font_render_mapping = load_font_render_mapping_rand(font_root)
    font_char_mapping, font_list = load_font_char_mapping(font_root)

    for font in font_render_mapping.keys():
        render = font_render_mapping[font]
        font_dict_in = font_char_mapping[font]
        text = ''.join(font_dict_in)
        all_chars = "!\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ" \
                    "[\]^_`abcdefghijklmnopqrstuvwxyz{" \
                    "|}‖·…。，,。.？?！!：；;·、………~～&＆@＠#＃“”‘’〝〞'＂＇【】《》＜＞﹝﹞<>[" \
                    "]«»‹›〔〕〈〉［］「」｛｝〖〗『』①②③④⑤⑥⑦⑧⑨⑩⑴⑵⑶⑷⑸⑹⑺⑻⑼⑽⑾⑿⒀⒁⒂⒃⒄⒅⒆⒇" \
                    "⒈⒉⒊⒋⒌⒍⒎⒏⒐⒑⒒⒓⒔⒕⒖⒗⒘⒙⒚⒛ⅠⅡⅢⅣⅤⅥⅦⅧⅨⅩⅪⅫ㈠㈡㈢㈣㈤㈥㈦㈧㈨㈩ⅰⅱⅲⅳⅴⅵⅶⅷⅸ" \
                    "﹢﹣/=﹤﹥≦≧≮≯≡＋－×÷＝＜＞≤≥≈≒≠﹢﹣±∶∵∴∷㏒㏑∑∏∅㎎㎏μm㎜㎝㎞¥$€㎡m³㏄" + text
        render.set_all_chars(all_chars)

    total = 0
    not_process_font = []
    for font in font_render_mapping:
        print('begin process font:' + font)
        all_chars = render.get_all_chars()
        img_num = 20 if is_debug else int(len(all_chars) * font_char_num / 10) + 1
        total = total + img_num

        # if total > 1220297:
        #     not_process_font.append(font)
        not_process_font.append(font)

    print("total:" + str(total))

    multiprocessing.set_start_method("spawn", force=True)
    manager = multiprocessing.Manager()
    data_queue = manager.Queue()

    db_writer_process = DBWriterProcess(
        data_queue, save_path, corp_img
    )
    db_writer_process.start()

    _processes_num = 2 if is_debug else 8
    # pool = multiprocessing.Pool(processes=_processes_num)
    with multiprocessing.Pool(
            # processes=_processes_num,
            # initializer=process_setup,
            # initargs=(),
    ) as pool:
        # for font in font_render_mapping:
        for font in not_process_font:
            render = font_render_mapping[font]
            pool.apply_async(run_by_round_rand,
                             (font, render, data_queue, font_char_num))
        pool.close()
        pool.join()

    data_queue.put(STOP_TOKEN)
    db_writer_process.join()


def effect_enmu_render():
    enum_render = EnumRender()

    font = 'Dengl.ttf'
    enum_render.set_font_path('D:/ocr/ocr_resources/reader/fonts/' + font)

    enum_render.set_num_image(100)

    text = '顔巷復誰堪竟日潛心到'
    enum_render.set_texts([text])
    datas = enum_render.process_img()
    for pos, data in enumerate(datas):
        info = {"image": data[0], "label": data[1], "char": 'char', "text": text, "font": font}
        image = info['image']
        if image is not None:
            img_path = 'D:/ocr/test/' + "test" + str(pos) + ".jpg"
            cv2.imwrite(img_path, image, [int(cv2.IMWRITE_JPEG_QUALITY), 95])


def effect_rand_render():
    render = RandRender()

    font = 'Dengl.ttf'
    render.set_font_path('D:/ocr/ocr_resources/reader/fonts/' + font)
    render.set_num_image(10)
    text = '顔巷復誰堪竟日潛心到num_image不能为空'
    render.set_all_chars(text)
    datas = render.process_img()

    img_root = 'D:/ocr/test/'
    for pos, data in enumerate(datas):
        info = {"image": data[0], "label": data[1], "char": 'char', "text": text, "font": font}
        image = info['image']
        if image is not None:
            img_path = img_root + "test" + str(pos) + ".jpg"
            # 获取图片的宽度和高度
            height, width = image.shape[:2]

            # 设置裁剪的左上角和右下角坐标
            # 注意：OpenCV中的坐标是以左上角为原点的
            x1, y1 = int(0), int(height * 0.2)
            x2, y2 = int(width), int(height * 0.8)

            # 使用切片操作进行裁剪
            crop_img = image[y1:y2, x1:x2]  # 3,28 25,231==>22,22 0,326
            cv2.imwrite(img_path, crop_img, [int(cv2.IMWRITE_JPEG_QUALITY), 95])

    # for img in os.listdir(img_root):
    #     if img.endswith('.jpg'):
    #         img_path = img_root + img
    #         image = cv2.imread(img_path)  # 设置裁剪区域
    #         # 获取图片的宽度和高度
    #         height, width = image.shape[:2]
    #
    #         # 设置裁剪的左上角和右下角坐标
    #         # 注意：OpenCV中的坐标是以左上角为原点的
    #         x1, y1 = int(width * 0.1), int(height * 0.1)
    #         x2, y2 = int(width * 0.9), int(height * 0.9)
    #
    #         # 使用切片操作进行裁剪
    #         crop_img = image[y1:y2, x1:x2]
    #         cv2.imwrite(img_root + 'corp' + img, crop_img, [int(cv2.IMWRITE_JPEG_QUALITY), 95])


if __name__ == "__main__":
    starttime = datetime.datetime.now()
    # ********************************v4 begin*************************#

    # pre_json_char_texts_mapping(reader_root + 'all_words/char_num_sort_10.txt', pre_char_texts_mapping_path_10,
    #                             dict_10)
    # pre_json_char_texts_mapping(reader_root + 'all_words/char_num_sort_10_no_dot.txt',
    #                             pre_char_texts_mapping_path_10_no_dot,
    #                             dict_10_no_dot)

    # font_char_mapping = load_font_char_mapping(font_root)
    # char_texts_mapping = load_char_texts_mapping(pre_char_texts_mapping_path)
    # font_render_mapping = load_font_render_mapping(font_root, save_path)
    # run_by_round(font_char_mapping, char_texts_mapping, font_render_mapping, '1')

    # round_by_pool(font_root, save_path, pre_char_texts_mapping_path_10)
    # labels_split('D:/ocr/ocr_resources/train_data/',
    #              ['char_enum_by_font'], 10000)
    # parse_char_num_mapping_of_file(save_path + 'labels.txt',
    #                                save_path + 'labels_mapping.txt')
    #
    # round_by_pool(font_root, save_path_no_dot, pre_char_texts_mapping_path_10_no_dot, 64, 10)
    # labels_split('D:/ocr/ocr_resources/reader/train_data/',
    #              ['char_enum_by_font_no_dot'], 10000, 0)
    # parse_char_num_mapping_of_file(save_path_no_dot + 'labels.txt',
    #                                save_path_no_dot + 'labels_mapping.txt')

    # ********************************v4 end*************************#
    # draw_large_text_to_image(font_root + 'Deng.ttf', get_txt_from_file(dot_dict_file), font_root + 'Deng.ttf.jpg')

    # dict_all = get_dict_from_file(pre_char_texts_mapping_path_10)
    # dict_in = get_dict_from_file('D:/workspace/python/train_data/train_data_configs/words/font/in_chars.txt')
    # dict_error = sub_dict(dict_all, dict_in)
    # print(dict_error)

    # effect_rand_render()

    # round_by_pool_rand(font_root, save_path_no_dot, 10)
    # labels_split('D:/ocr/ocr_resources/reader/train_data/',
    #              ['char_enum_by_font_no_dot'], 10000, 0)
    # parse_char_num_mapping_of_file(save_path_no_dot + 'labels.txt',
    #                                save_path_no_dot + 'labels_mapping.txt')

    # round_by_pool_rand(font_root, save_path_no_dot, 2, True)
    labels_split('D:/ocr/ocr_resources/reader/train_data/',
                 ['char_enum_by_font_no_dot'], 10000, 0)
    parse_char_num_mapping_of_file(save_path_no_dot + 'labels.txt',
                                   save_path_no_dot + 'labels_mapping.txt')

    endtime = datetime.datetime.now()
    seconds = (endtime - starttime).seconds
    m, s = divmod(seconds, 60)
    h, m = divmod(m, 60)
    print("%d:%02d:%02d" % (h, m, s))
